﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Chbl.Models;

namespace Chbl.ViewModels
{
    public class StandingsViewModel
    {
        private Dictionary<Team, TeamStandingViewModel> StandingsDict { get; set; }

        public StandingsViewModel(IEnumerable<Team> teams)
        {
            StandingsDict = new Dictionary<Team, TeamStandingViewModel>();
            Teams = teams.ToList();
            foreach (Team team in teams)
            {
                StandingsDict.Add(team, new TeamStandingViewModel
                                            {
                                                Team = team, 
                                                LostGames = 0, 
                                                BallsScored = 0,
                                                BallsSkipped = 0,
                                                WonGames = 0
                                            });
            }
        }

        public StandingsViewModel(IEnumerable<TeamStandingViewModel> overallStandings)
        {            
            StandingsDict = new Dictionary<Team, TeamStandingViewModel>();
            Teams = overallStandings.Select(st => st.Team).ToList();
            foreach (TeamStandingViewModel teamStanding in overallStandings)
            {
                StandingsDict.Add(teamStanding.Team, new TeamStandingViewModel
                                                         {
                                                             OverallTeamStanding = teamStanding,
                                                             Team = teamStanding.Team
                                                         });
            }
        }
        public List<Team> Teams { get; private set; }
        
        public void ProcessGame(Game game)
        {
            if (!(game.HomeScore.HasValue && game.RoadScore.HasValue))
                return;

            TeamStandingViewModel homeTeamStanding = StandingsDict[game.HomeTeam];
            homeTeamStanding.BallsScored += game.HomeScore.Value;
            homeTeamStanding.BallsSkipped += game.RoadScore.Value;

            TeamStandingViewModel roadTeamStanding = StandingsDict[game.RoadTeam];
            roadTeamStanding.BallsScored += game.RoadScore.Value;
            roadTeamStanding.BallsSkipped += game.HomeScore.Value;

            if (game.HomeScore.Value > game.RoadScore.Value )
            {                
                homeTeamStanding.WonGames++;
                roadTeamStanding.LostGames++;
            }
            else
            {
                homeTeamStanding.LostGames++;
                roadTeamStanding.WonGames++;
            }

            if (game.TechnicalDefeat.HasValue && game.TechnicalDefeat.Value)
            {
                if (game.HomeScore.Value > game.RoadScore.Value)
                {
                    roadTeamStanding.TechnicalDefeats++;
                }
                else
                {
                    homeTeamStanding.TechnicalDefeats++;
                }
            }
        }

        public IEnumerable<TeamStandingViewModel> GetStandings(ScheduleViewModel scheduleViewModel)
        {
            List<TeamStandingViewModel> standingList = StandingsDict.Values.ToList();            
            IEnumerable<int> pointValues = standingList.Select(ts => ts.Points).Distinct().OrderByDescending(p => p);
            int teamPlace = 1;
            foreach (var pointValue in pointValues)
            {
                int pointValueLocal = pointValue;
                List<TeamStandingViewModel> standingsWithEquilPoints = standingList.Where(tm => tm.Points == pointValueLocal).ToList();
                if (standingsWithEquilPoints.Count() == 1)
                {
                    standingsWithEquilPoints.First().Place = teamPlace;
                    teamPlace++;
                }
                else
                {
                    ProcessRepeatClassification(standingsWithEquilPoints, ref teamPlace, scheduleViewModel);
                }
            }
            return standingList.OrderBy(st => st.Place);
        }

        private static void ProcessRepeatClassification(
            IEnumerable<TeamStandingViewModel> standingsWithEquilPoints, 
            ref int teamPlace, 
            ScheduleViewModel scheduleViewModel)
        {
            StandingsViewModel repeatedStanding = new StandingsViewModel(standingsWithEquilPoints);
            foreach (Game game in scheduleViewModel.Games.Where(g => repeatedStanding.Teams.Contains(g.HomeTeam) 
                && repeatedStanding.Teams.Contains(g.RoadTeam)))
            {
                repeatedStanding.ProcessGame(game);
            }
            List<TeamStandingViewModel> additionalStandings = repeatedStanding.StandingsDict.Values.ToList();
            additionalStandings.Sort(CompareTeamStanding);
            foreach (var teamStandingViewModel in additionalStandings)
            {
                TeamStandingViewModel model = teamStandingViewModel;
                standingsWithEquilPoints.Where(ts => ts.Team == model.Team).First().Place = teamPlace;
                teamPlace++;
            }
        }

        private static int CompareTeamStanding(TeamStandingViewModel left, TeamStandingViewModel right)
        {
            if (left.Points > right.Points)
                return -1;
            if (left.Points < right.Points)
                return 1;
            if (left.BallsFactor > right.BallsFactor)
                return -1;
            if (left.BallsFactor < right.BallsFactor)
                return 1;
            if (left.OverallTeamStanding.BallsFactor > right.OverallTeamStanding.BallsFactor)
                return -1;
            if (left.OverallTeamStanding.BallsFactor < right.OverallTeamStanding.BallsFactor)
                return 1;
            return 0;
        }

    }
}